package org.lmind.scale.study

import java.io.Closeable

class Property[T](init: T) {
  private var value: T = init

  /** The getter function, defaults to identity. */
  private var setter: T => T = identity[T]

  /** The setter function, defaults to identity. */
  private var getter: T => T = identity[T]

  /** Retrive the value held in this property.   */
  def apply(): T = getter(value)

  /** Update the value held in this property, through the setter. */
  def update(newValue: T) = value = setter(newValue)

  /** Change the getter. */
  def get(newGetter: T => T) = { getter = newGetter; this }

  /** Change the setter */
  def set(newSetter: T => T) = { setter = newSetter; this }
}

class Property2[T](init: T) {
  
  private var value: T = init
  
  def fn : (T) => T = 
    (x) => x

  /** Retrive the value held in this property.   */
  def apply(): T = value

  /** Update the value held in this property, through the setter. */
  def update(newValue: T) = value = newValue
}

class User {
  // Create a property with custom getter and setter
  val firstname = new Property("")
    .get { v => v.toUpperCase() }
    .set { v => "Mr. " + v }
  val lastname = new Property("<noname>")

  override def toString() = firstname() + " " + lastname()
}

object PropertyTest {

  def main(args: Array[String]) {
    
    val user1 = new User
    
    val s = new Property2()
    s.update(13)

    // Syntactic sugar for 'update': an assignment is translated to a
    // call to method 'update'
    user1.firstname() = "Robert"

    val user2 = new User
    user2.firstname() = "bob"
    user2.lastname() = "KUZ"

    println("user1: " + user2.firstname())
    println("user2: " + user2.lastname())
  }
}